<?php
namespace app\task\controller;
use app\common\library\wechat\WxBizMsgCrypt;
use app\task\model\Config as ConfigModel;
use app\task\model\Wxapp as WxappModel;
use app\task\model\Wechat as WechatModel;
use app\task\model\WebSet as WebSetModel;
use app\task\model\Keyword as KeywordModel;
use app\task\model\StoreUser;
use app\task\model\Setting;
use app\task\model\WxappTpl as WxappTplModel;
use app\task\model\Nearby as NearbyModel;
use app\task\model\WechatBatchSend as WechatBatchSendModel;
use think\Session;
/**
 * 第三方平台与微信通讯接口
 */
class Wechat extends \think\Controller
{
	protected $wechat;    //公众号
    /**
     * 异步通知处理
     */
    public function callback($appid='')
    {
    	$this->wechat = WechatModel::getWechat(['app_id' => $appid]);
		// 接收公众号平台发送的消息
		$nonce = empty ( $_GET ['nonce'] ) ?"" : trim ( $_GET ['nonce'] );
		$signature = empty ( $_GET['signature'] ) ? "" : trim ( $_GET ['signature'] );
		$timeStamp = empty ( $_GET ['timestamp']) ? "" : trim ( $_GET ['timestamp'] );
		$msg_signature = empty ( $_GET['msg_signature'] ) ? "" : trim ( $_GET ['msg_signature'] );
		$encryptMsg = file_get_contents ('php://input' );
		//获取第三方配置信息
		$config = ConfigModel::detail();
        //创建解密类
		$pc = new WxBizMsgCrypt($config['token'], $config['encoding_aes_key'], $config['app_id']);
		$msg = '';		
		$errCode = $pc->decryptMsg($msg_signature, $timeStamp, $nonce, $encryptMsg, $msg);	
		if($errCode == 0){
			$data = _xmlToArr($msg);	//XML转换为数组
			write_log($data, __DIR__);
			//*********************************接收事件推送*****************************************
			if($data['MsgType']=='event'){
				//用户未关注时，进行关注后的事件推送
				if($data['Event']=='subscribe'){
					//是否设置了关注回复
					if($subscribe = Setting::getItem('subscribe')){
						$this->replyMsg($subscribe,$data);//回复信息
					} 
					//获取粉丝资料
					if($user = getWechatUserInfo($data['FromUserName'],$this->wechat['wxapp_id'])){
						//用户操作
						if($new_user = $this->addUser($user,'edit')){
							$store_wxapp = WebSetModel::getItem('wxapp');
							$this->sendServiceMsg([
									'type' => 'text',
									'content' => '请妥善保管您的账号和密码~
如忘记回复“找回账号”找回~
账号：' . $new_user['user_name'] . '
密码：' . $new_user['password'] . '
<a href="http://www.qq.com" data-miniprogram-appid="'.$store_wxapp['app_id'].'" data-miniprogram-path="pages/index/index">点此跳转商家助手小程序 >></a>'
								],$data);
						}
					}else{
						//返回文本提醒
						$this->sendServiceMsg([
							'type' => 'text',
							'content' => '公众号未关联开放平台，会影响后续使用！'
						],$data);
					}
					return '';//阻止重复推送
				}
				
				//用户已关注时扫码进入事件推送
				if($data['Event']=='SCAN'){
					
				}
				//取消关注事件
				if($data['Event']=='unsubscribe'){
					if($store = StoreUser::getStore(['wechat_open_id' => $data['FromUserName']])){
						$store->unSubscribe();
					}
					return '';//阻止重复推送
				}
				
				//扫描带参数二维码事件 - 用户未关注时，进行关注后的事件推送
				if($data['Event']=='subscribe' AND isset($data['EventKey'])){
		
				}
				
				//扫描带参数二维码事件 - 用户已关注时的事件推送
				if($data['Event']=='SCAN'){
				
				}
				
				//上报地理位置事件
				if($data['Event']=='LOCATION'){
					
				}
				
				//自定义菜单事件 - 点击菜单拉取消息时的事件推送
				if($data['Event']=='CLICK'){
					$this->textMsg($data);
				}
				
				//自定义菜单事件 - 点击菜单跳转链接时的事件推送
				if($data['Event']=='VIEW'){
					
				}
				//添加附近门店类目审核回调
				if($data['Event']=='nearby_category_audit_info'){
					//$this->nearby_category_audit_info($data);
				}
				
				//添加附近小程序地点审核回调
				if($data['Event']=='add_nearby_poi_audit_info'){
					write_log('添加附近小程序地点审核回调',__DIR__);
					write_log($data,__DIR__);
					$this->add_nearby_poi_audit_info($data);
				}
				
				//群发任务回调事件推送
				if($data['Event']=='MASSSENDJOBFINISH'){
					$msg = WechatBatchSendModel::getMsg($data['MsgID']);
					$msg->edit($data);
				}

				//代码审核成功结果推送
				if($data['Event'] == 'weapp_audit_success'){
					//获取商户数据
					if($wxapp = WxappModel::getWxapp([
						'user_name' => $data['ToUserName']
					])){ 
						//发布小程序模板
						if(!$result = release($wxapp['wxapp_id'])){
							$tpl = WxappTplModel::getNew($wxapp['wxapp_id']);
							$tpl->edit(['status' => 1]);
						}
					}
				}
			}
			//*********************************接收普通消息*****************************************
			//接收普通消息 - 文本消息
			if($data['MsgType']=='text'){
				write_log('aaaaaaaaaaaaaa',__DIR__);
				$this->textMsg($data);//文本消息处理
			}
			
			//接收普通消息 - 图片消息
			if($data['MsgType']=='image'){
				//发什么回什么
				echo $this->msgTpl([
					'ToUserName' => $data['FromUserName'],
					'FromUserName' => $data['ToUserName'],
					'MsgType' => $data['MsgType'],
					'MediaId' => $data['MediaId']
				]);
			}
			
			//接收普通消息 - 语音消息
			if($data['MsgType']=='voice'){
				//发什么回什么
				echo $this->msgTpl([
					'ToUserName' => $data['FromUserName'],
					'FromUserName' => $data['ToUserName'],
					'MsgType' => $data['MsgType'],
					'MediaId' => $data['MediaId']
				]);
			}
			
			//接收普通消息 - 视频消息
			if($data['MsgType']=='video'){
				//发什么回什么
				echo $this->msgTpl([
					'ToUserName' => $data['FromUserName'],
					'FromUserName' => $data['ToUserName'],
					'MsgType' => 'text',
					'Content' => '我不看，太低俗~'
				]);
			}
			
			//接收普通消息 - 小视频消息
			if($data['MsgType']=='shortvideo'){
				
			}
			
			//接收普通消息 - 地理位置消息
			if($data['MsgType']=='location'){
				
			}
			
			//接收普通消息 - 链接消息
			if($data['MsgType']=='link'){
				
			}
			return 'success';
		}else{
			write_log('Wechat 解密失败 - 错误代码：'.$errCode, __DIR__);
		}
    }

    /**
     * 微信扫码登录
     */
    public function login($code='',$state)
    {
		//获取第三方配置信息
		$values = WebSetModel::getItem('wxweb');
		if(empty($code) OR empty($values['app_id']) OR empty($values['app_secret'])){
			return '参数错误';
		}
    	//通过code获取access_token
		$url = 'https://api.weixin.qq.com/sns/oauth2/access_token';
        $result = json_decode(curl($url, [
            'appid' => $values['app_id'],
            'secret' => $values['app_secret'],
            'grant_type' => 'authorization_code',
            'code' => $code
        ]), true);
        //如果获取access_token失败
	    if(!isset($result['access_token'])){
	    	return '获取access_token失败';
	    }
	    //获取用户信息
	    $url = 'https://api.weixin.qq.com/sns/userinfo';
        $result = json_decode(curl($url, [
            'access_token' => $result['access_token'],
            'openid' => $result['openid'],
            'lang' => 'zh_CN'
        ]), true);
        //如果获取成功
        if(isset($result['unionid'])){
        	$data = [
        		'union_id' => $result['unionid'],
				'web_open_id' => $result['openid'],
				'nickName' => preg_replace('/[\xf0-\xf7].{3}/', '', $result['nickname']),
				'avatarUrl' => $result['headimgurl'],
				'gender' => $result['sex'],
				'country' => $result['country'],
				'province' => $result['province'],
				'city' => $result['city']
			];
			//用户操作
        	if(!$result = $this->addUser($data)){
        		return '用户验证失败';
        	}
        	if($store = StoreUser::getStore([
				'union_id' => $data['union_id']
			])){
	        	// 保存登录状态
				Session::set('hema_store', [
					'user' => [
						'store_user_id' => $store['store_user_id'],
						'user_name' => $store['user_name'],
						'agent_id' => $store['agent_id'],
                    	'avatarUrl' => $store['avatarUrl']
					],
					'is_login' => true,
					'is_admin' => true,
				]);
			}else{
				return '获取用户信息失败';
			}
		}else{
			return '获取用户信息失败';
		}
		$this->redirect('/login.php');
	}

	/**
     * 新增用户
     */
	private function addUser($data,$mode = 'add')
	{
		//查询是否为历史用户
		if(!$store = StoreUser::getStore([
			'union_id' => $data['union_id']
		])){
			$user = new StoreUser;
			return $user->add($data);
		}
		if($mode == 'edit' OR empty($store['user_name'])){
			return $store->edit($data);
		}
		return true;
	}
	
	/**
     * 附近门店类目回调处理
    
	private function nearby_category_audit_info($data)
	{
		$model = NearbyCategoryModel::getDetail(['audit_id' => $data['audit_id']]);
		$model->edit($data);
	}
	*/
	/**
     * 添加附近展示地点回调处理
    */
	private function add_nearby_poi_audit_info($data)
	{
		$model = NearbyModel::getDetail(['audit_id' => $data['audit_id']]);
		$model->edit($data);
	}
	
	/**
     * 处理文本消息
    */
	private function textMsg($data)
	{
		//判断是否来自公众号菜单
		if(isset($data['EventKey'])){
			$data['Content'] = $data['EventKey'];
			$data['MsgType'] = 'text';
		}
		//是否设置了关键字回复
		switch($data['Content']){
			case 'id':
				echo $this->msgTpl([
						'ToUserName' => $data['FromUserName'],
						'FromUserName' => $data['ToUserName'],
						'MsgType' => 'text',
						'Content' => $data['FromUserName']
					]);
				break;
			case '找回账号':
				//获取用户信息ID
				if($user = StoreUser::getStore(['wechat_open_id' => $data['FromUserName']])){
					if($new_user = $user->edit()){
						echo $this->msgTpl([
							'ToUserName' => $data['FromUserName'],
							'FromUserName' => $data['ToUserName'],
							'MsgType' => 'text',
							'Content' => '恭喜：成功找回账号~
提醒：每次找回都要重置密码~
您的账号：' . $new_user['user_name'] . '
您的密码：' . $new_user['password']
						]);	
					}			
				}else{
					//返回文本提醒
					echo $this->msgTpl([
						'ToUserName' => $data['FromUserName'],
						'FromUserName' => $data['ToUserName'],
						'MsgType' => 'text',
						'Content' => '账号异常~
请取消关注该公众号后，在重新关注后进行操作。'
					]);
				}
				break;
			default:
				if($values = KeywordModel::getKey($data['Content'],$this->wechat['wxapp_id'])){
					write_log($values,__DIR__);
					$this->replyMsg($values,$data);//回复信息
				}else{
					if($values = KeywordModel::getKey('*')){
						$this->replyMsg($values,$data);//回复信息
					}else{
						//没有，发什么回什么
						echo $this->msgTpl([
							'ToUserName' => $data['FromUserName'],
							'FromUserName' => $data['ToUserName'],
							'MsgType' => $data['MsgType'],
							'Content' => $data['Content']
						]);
					}
				}
		}
	}
	
	/**
     * 回复消息
    */
	private function replyMsg($msg,$data)
	{
		//是否开启
		if($msg['is_open']==1){
			//文字消息
			if($msg['type']=='text'){
				echo $this->msgTpl([
					'ToUserName' => $data['FromUserName'],
					'FromUserName' => $data['ToUserName'],
					'MsgType' => 'text',
					'Content' => $msg['content']['description']
				]);
			}			
			//图片消息
			if($msg['type']=='image'){
				echo $this->msgTpl([
				  'ToUserName' => $data['FromUserName'],
				  'FromUserName' => $data['ToUserName'],
				  'MsgType' => 'image',
				  'MediaId' => $msg['content']['media_id']
				]);
			}
			//语音消息
			if($msg['type']=='voice'){
				echo $this->msgTpl([
				  'ToUserName' => $data['FromUserName'],
				  'FromUserName' => $data['ToUserName'],
				  'MsgType' => 'voice',
				  'MediaId' => $msg['content']['media_id']
				]);
			}
			//视频消息
			if($msg['type']=='video'){
				echo $this->msgTpl([
				  'ToUserName' => $data['FromUserName'],
				  'FromUserName' => $data['ToUserName'],
				  'MsgType' => 'video',
				  'Title' => $msg['content']['title'],
				  'Description' => $msg['content']['description'],
				  'MediaId' => $msg['content']['media_id']
				]);	
			}
			//音乐消息
			if($msg['type']=='music'){
				echo $this->msgTpl([
				  'ToUserName' => $data['FromUserName'],
				  'FromUserName' => $data['ToUserName'],
				  'MsgType' => 'music',
				  'Title' => $msg['content']['title'],
				  'Description' => $msg['content']['description'],
				  'MusicUrl' => $msg['content']['url'],
				  'HQMusicUrl' => $msg['content']['hurl'],
				  'ThumbMediaId' => $msg['content']['media_id']
				]);
			}
			//图文消息
			if($msg['type']=='news'){
				echo $this->msgTpl([
				  'ToUserName' => $data['FromUserName'],
				  'FromUserName' => $data['ToUserName'],
				  'MsgType' => 'news',
				  'Articles' => [
				  	'title' => $msg['content']['title'],
				  	'description' => $msg['content']['description'],
				  	'picurl' => $msg['content']['picurl'],
				  	'url' => $msg['content']['url']
				  ]
				]);
			}
		}
	}
	
	/**
     * 发送客服消息模板
    */
	private function sendServiceMsg($msg,$data)
	{
		//文本消息
		if($msg['type']=='text'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'text',
				'text' => [
					'content' => $msg['content']
				]
			];
		}
		//图片消息
		if($msg['type']=='image'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'image',
				'image' => [
					'media_id' => $msg['media_id']
				]
			];
		}
		//图文消息（点击跳转到图文消息页面） 图文消息条数限制在1条以内
		if($msg['type']=='mpnews'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'mpnews',
				'mpnews' => [
					'media_id' => $msg['media_id']
				]
			];
		}
		//发送图文消息（点击跳转到外链） 图文消息条数限制在1条以内
		if($msg['type']=='news'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'news',
				'news' => [
					'articles' => [
						'picurl' => $msg['picurl'],
						'url' => $msg['url'],
						'title' => $msg['title'],
						'description' => $msg['description']
					]
				]
			];
		}
		//语音消息
		if($msg['type']=='voice'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'voice',
				'voice' => [
					'media_id' => $msg['media_id']
				]
			];
		}
		//视频消息
		if($msg['type']=='video'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'video',
				'video' => [
					'media_id' => $msg['media_id'],
					'thumb_media_id' => $msg['thumb_media_id'],
					'title' => $msg['title'],
					'description' => $msg['description']
				]
			];
		}
		//音乐消息
		if($msg['type']=='music'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'music',
				'video' => [
					'musicurl' => $msg['musicurl'],
					'thumb_media_id' => $msg['thumb_media_id'],
					'title' => $msg['title'],
					'hqmusicurl' => $msg['hqmusicurl'],
					'description' => $msg['description']
				]
			];
		}

		//发送小程序卡片（要求小程序与公众号已关联）
		if($msg['type']=='wxapp'){
			$tpl = [
				'touser' => $data['FromUserName'],
				'msgtype' => 'miniprogrampage',
				'miniprogrampage' => [
					'pagepath' => $msg['pagepath'],
					'thumb_media_id' => $msg['thumb_media_id'],
					'title' => $msg['title'],
					'appid' => $msg['appid'],
					'description' => $msg['description']
				]
			];
		}
		if(isset($tpl)){
			$access_token = getAccessToken('',0);
			$url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token='.$access_token;
			$result = json_decode(http_post($url,$tpl),true);
			if($result['errcode'] == 0){
				return true;
			}
		}
		return false;
	}
	
	/**
     * 将array转为xml
    */
	private function msgTpl($arr)
	{
		$xml ="<xml><ToUserName><![CDATA[" . $arr['ToUserName'] . "]]></ToUserName>";
		$xml .="<FromUserName><![CDATA[" . $arr['FromUserName'] . "]]></FromUserName>";
		$xml .="<CreateTime>" . time() . "</CreateTime>";
		$xml .="<MsgType><![CDATA[" . $arr['MsgType'] . "]]></MsgType>";
		switch($arr['MsgType']){
			case "text":
				$xml .="<Content><![CDATA[" . $arr['Content'] . "]]></Content>";
				break;
			case "image":
				$xml .= "<Image><MediaId><![CDATA[" . $arr['MediaId'] . "]]></MediaId></Image>";
				break;
			case "voice":
				$xml .= "<Voice><MediaId><![CDATA[" . $arr['MediaId'] . "]]></MediaId></Voice>";
				break;
			case "video":
				$xml .= "<Video><MediaId><![CDATA[" . $arr['MediaId'] . "]]></MediaId><Title><![CDATA[" . $arr['Title'] . "]]></Title><Description><![CDATA[" . $arr['Description'] . "]]></Description></Video>";
				break;
			case "music":
				$xml .= "<Music><Title><![CDATA[" . $arr['Title'] . "]]></Title><Description><![CDATA[" . $arr['Description'] . "]]></Description><MusicUrl><![CDATA[" . $arr['MusicUrl'] . "]]></MusicUrl><HQMusicUrl><![CDATA[" . $arr['HQMusicUrl'] . "]]></HQMusicUrl><ThumbMediaId><![CDATA[" . $arr['ThumbMediaId'] . "]]></ThumbMediaId></Music>";
				break;
			case "news":
				$xml .= "<ArticleCount>1</ArticleCount><Articles>";
				$xml .= "<item><Title><![CDATA[". $arr['Articles']['title'] ."]]></Title><Description><![CDATA[". $arr['Articles']['description'] ."]]></Description><PicUrl><![CDATA[". $arr['Articles']['picurl'] ."]]></PicUrl><Url><![CDATA[". $arr['Articles']['url'] ."]]></Url></item>";
				$xml .= "</Articles>";
				break;
		}
		$xml .= "</xml>";
		return $xml;
	}
}
